﻿using System;
using System.Collections;
using System.Configuration.Install;
using System.ServiceModel;
using System.ServiceProcess;

namespace WOLGateway.WindowsService
{
    /// <summary>
    /// Program
    /// </summary>
    public static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        /// <param name="args">The args.</param>
        internal static void Main(string[] args)
        {
            if (Environment.UserInteractive) // Within a shell, e.g. cmd.exe
            {
                if (args.Length > 0)
                {
                    switch (args[0])
                    {
                        case "-i":
                            Console.WriteLine("Install service");
                            InstallService(typeof(Program));
                            break;

                        case "-u":
                            Console.WriteLine("Uninstall service");
                            InstallService(typeof(Program), true);
                            break;
                    }
                }
                else
                {
                    Console.WriteLine("Start as console app");
                    // Start the WCF service in a console app
                    using (var host = new WindowsService())
                    {
                        try
                        {
                            host.Open();
                            Console.WriteLine("WOLGateway service successfully started.");
                            Console.WriteLine("Press any key to quit...");
                            Console.ReadKey();
                            host.Close();

                            Console.WriteLine("WOLGateway service terminated.");
                        }
                        catch (System.ServiceProcess.TimeoutException timeProblem)
                        {
                            Console.WriteLine(timeProblem.Message);
                            Console.WriteLine("Press any key to quit...");
                            Console.ReadKey();
                        }
                        catch (CommunicationException commProblem)
                        {
                            Console.WriteLine(commProblem.Message);
                            Console.WriteLine("Press any key to quit...");
                            Console.ReadKey();
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            Console.WriteLine("Press any key to quit...");
                            Console.ReadKey();
                        }
                    }
                }
            }
            else
            {
                // start the service as windows service
                ServiceBase[] servicesToRun = new ServiceBase[] { new WindowsService() };
                ServiceBase.Run(servicesToRun);
            }
        }

        /// <summary>
        /// Installs the service.
        /// </summary>
        /// <param name="program">Type of the entry point (e.g. Program) of the assembly to install</param>
        /// <param name="uninstall">If set to <c>true</c> uninstall the service.</param>
        private static void InstallService(Type program, bool uninstall = false)
        {
            try
            {
                string[] args = { "/LogToConsole=true", "/ShowCallStack=true" };
                using (AssemblyInstaller assemblyInstaller = new AssemblyInstaller(program.Assembly, args))
                {
                    IDictionary state = new Hashtable();
                    assemblyInstaller.UseNewContext = true;
                    try
                    {
                        if (uninstall)
                        {
                            assemblyInstaller.Uninstall(state);
                        }
                        else
                        {
                            assemblyInstaller.Install(state);
                            assemblyInstaller.Commit(state);
                        }
                    }
                    catch
                    {
                        try
                        {
                            assemblyInstaller.Rollback(state);
                        }
                        catch
                        { }
                        throw;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.Message);
            }
        }
    }
}